package TabuSearch;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Tabusearch {
	private static List<Estacao> estacoes = new ArrayList<Estacao>();
	private static Set<Integer> pontos = new HashSet<Integer>();
	private static int numPontos;
	private static int numEstacoes;
	private static int[][] listaTabu;
	private static int[] coberturaPontos;
	
	public static void main(String[] args) {
		List<Estacao> melhorSolucao = null;
		float menorCusto = -1;
		int iteracaoMelhorSol = 0;
		inicializar(args[0]);
		int iteracao = 0;
		HeuristicaRefinamento hRefin = new HeuristicaRefinamento(estacoes);
		HeuristicaConstrutora h = new HeuristicaConstrutora(); 
		List<Estacao> sol = h.geraSolucaoInicial(clonar(estacoes), coberturaPontos);
		if (sol != null){
			long tempoInicial = System.currentTimeMillis();
			long tempoFinal = tempoInicial;
			while ((tempoFinal - tempoInicial < 60000) && (iteracao-iteracaoMelhorSol<50)){
				sol = hRefin.escolheMelhorMovimento(iteracao, coberturaPontos, listaTabu, sol);
				float novoCusto = getcusto(sol);
				if (menorCusto == -1 || novoCusto<menorCusto){
					menorCusto = novoCusto;
					melhorSolucao = clonar(sol);
					iteracaoMelhorSol = iteracao;
				}
				iteracao++;
				tempoFinal = System.currentTimeMillis();
			}
			if (tempoFinal - tempoInicial > 60000)
				System.out.println("tempo");
			//System.out.println(menorCusto);
			//System.out.println(tempoFinal-tempoInicial);
			System.out.println("Valor: "+ menorCusto);
			System.out.println("Total: "+melhorSolucao.size());
			for (int i=0; i<melhorSolucao.size(); i++)
				System.out.println(melhorSolucao.get(i).getNome());
		}
		else
			System.out.println("Instancia infactivel");
	}
	
	
	private static float getcusto(List<Estacao> sol) {
		float custo = 0;
		for (int i=0; i<sol.size(); i++)
			custo += (sol.get(i)).getCusto();
		return custo;
	}
	
	private static List<Estacao> clonar(List<Estacao> lista){
		List<Estacao> nova = new ArrayList<Estacao>();
		for (int i=0; i<lista.size(); i++)
			nova.add(lista.get(i));
		return nova;
	}

	private static void inicializar(String inst){
		try {
			BufferedReader in = new BufferedReader(new FileReader(inst));
			String str;
			str = in.readLine();
			String[] valores = str.split(" ");
			numPontos = Integer.parseInt(valores[1]);
			str = in.readLine();
			valores = str.split(" ");
			numEstacoes = Integer.parseInt(valores[1]);
			
			while (in.ready()) {
				str = in.readLine();
				valores = str.split(" ");
				Estacao novaEstacao = new Estacao(valores[0], Float.parseFloat(valores[1]));
				List<Integer> pontosCobList = new ArrayList<Integer>();
				for (int i=2; i<valores.length; i++){
					pontosCobList.add(Integer.parseInt(valores[i]));
					pontos.add(Integer.parseInt(valores[i]));
				}
				novaEstacao.setPontosCobertos(pontosCobList);
				novaEstacao.setCustoPorPonto();
				estacoes.add(novaEstacao);
			}
			in.close();
			coberturaPontos = new int[numPontos];
			for (int i=0; i<numPontos; i++){
				coberturaPontos[i] = 0;
			} 
			listaTabu = new int[numEstacoes][2];
			for (int i=0; i<numEstacoes; i++){
				listaTabu[i][0] = 0;
				listaTabu[i][1] = 0;
			} 
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
